package com.gitee.wsl.collections.deque

import com.gitee.wsl.func.consumer.Consumer


/**
 * Provides a reverse-ordered view of any Deque. Not serializable.
 */
internal class ReverseOrderDequeView<E> private constructor(
    val base: Deque<E>
) : Deque<E> {

    // ========== Iterable ==========
    fun forEach(action: Consumer<in E>) {
        for (e in this) action.accept(e)
    }

    override fun iterator(): MutableIterator<E> {
        return base.descendingIterator()
    }


    // ========== Collection ==========
    override fun add(element: E): Boolean {
        base.addFirst(element)
        return true
    }

    override fun addAll(elements: Collection<E>): Boolean {
        var modified = false
        for (e in elements) {
            base.addFirst(e)
            modified = true
        }
        return modified
    }

    override fun clear() {
        base.clear()
    }

    override fun contains(element: E): Boolean {
        return base.contains(element)
    }

    override fun containsAll(elements: Collection<E>): Boolean {
        return base.containsAll(elements)
    }

    override fun isEmpty(): Boolean {
        return base.isEmpty()
    }

//    fun parallelStream(): Stream<E> {
//        return StreamSupport.stream(spliterator(), true)
//    }

    // copied from AbstractCollection
    override fun remove(element: E): Boolean {
        val it: MutableIterator<E?> = iterator()
        if (element == null) {
            while (it.hasNext()) {
                if (it.next() == null) {
                    it.remove()
                    return true
                }
            }
        } else {
            while (it.hasNext()) {
                if (element == it.next()) {
                    it.remove()
                    return true
                }
            }
        }
        return false
    }

    // copied from AbstractCollection
    override fun removeAll(elements: Collection<E>): Boolean {

        var modified = false
        val it: MutableIterator<*> = iterator()
        while (it.hasNext()) {
            if (elements.contains(it.next())) {
                it.remove()
                modified = true
            }
        }
        return modified
    }

    // copied from AbstractCollection
    override fun retainAll(elements: Collection<E>): Boolean {
        var modified = false
        val it = iterator()
        while (it.hasNext()) {
            if (!elements.contains(it.next())) {
                it.remove()
                modified = true
            }
        }
        return modified
    }

    override val size: Int
        get() =  base.size


    // copied from AbstractCollection
    override fun toString(): String {
        val it: Iterator<E> = iterator()
        if (!it.hasNext()) return "[]"

        val sb = StringBuilder()
        sb.append('[')
        while (true) {
            val e = it.next()
            sb.append(if (e === this) "(this Collection)" else e)
            if (!it.hasNext()) return sb.append(']').toString()
            sb.append(',').append(' ')
        }
    }

    // ========== Deque and Queue ==========
    override fun addFirst(e: E) {
        base.addLast(e)
    }

    override fun addLast(e: E) {
        base.addFirst(e)
    }

    override fun descendingIterator(): MutableIterator<E> {
        return base.iterator()
    }

    override fun element() = base.getLast()!!


    override fun getFirst() = base.getLast()


    override fun getLast() = base.getFirst()


    override fun offer(e: E): Boolean {
        return base.offerFirst(e)
    }

    override fun offerFirst(e: E): Boolean {
        return base.offerLast(e)
    }

    override fun offerLast(e: E): Boolean {
        return base.offerFirst(e)
    }

    override fun peekOrNull() = base.peekLast()


    override fun peekFirst()= base.peekLast()


    override fun peekLast() = base.peekFirst()


    override fun pollOrNull() = base.pollLast()


    override fun pollFirst() = base.pollLast()


    override fun pollLast() = base.pollFirst()


    override fun pop() = base.removeLast()


    override fun push(e: E) = base.addLast(e)


    override fun remove() = base.removeLast()


    override fun removeFirst() = base.removeLast()


    override fun removeLast() = base.removeFirst()


    override fun removeFirstOccurrence(o:E): Boolean {
        return base.removeLastOccurrence(o)
    }

    override fun removeLastOccurrence(o: E): Boolean {
        return base.removeFirstOccurrence(o)
    }

    companion object {
        fun <T> of(deque: Deque<T>): Deque<T> {
            return if (deque is ReverseOrderDequeView<T>) {
                deque.base
            } else {
                ReverseOrderDequeView(deque)
            }
        }
    }
}
